package cn.liziguo.tank.script;

import cn.liziguo.tank.constants.CampEnum;
import cn.liziguo.tank.constants.GameEnum;
import cn.liziguo.tank.constants.PropertyConst;
import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.entity.component.Component;
import javafx.geometry.Point2D;
import javafx.util.Duration;

import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author Liziguo
 * @date 2022/7/12 18:21
 */
public class ShockWaveComponent extends Component {
    public static final GameEnum[] PLAYER = {GameEnum.ENEMY, GameEnum.HOME, GameEnum.BULLET, GameEnum.BRICK, GameEnum.STONE, GameEnum.GREENS};
    public static final GameEnum[] ENEMY = {GameEnum.PLAYER, GameEnum.HOME, GameEnum.BULLET, GameEnum.BRICK, GameEnum.STONE, GameEnum.GREENS};

    private final Set<BaseTankComponent> set = new HashSet<>();

    private final Point2D point;
    private final double maxRadius;
    private final double minRadius;
    private final long time;
    private final boolean camp;
    private final int attack;

    private final long startTime;

    public ShockWaveComponent(Point2D point, double maxRadius, double minRadius, long time, boolean camp, int attack) {
        this.point = point;
        this.maxRadius = maxRadius;
        this.minRadius = minRadius;
        this.time = time;
        this.camp = camp;
        this.attack = attack;
        startTime = System.currentTimeMillis();
    }

    @Override
    public void onUpdate(double tpf) {
        double maxRadius = this.maxRadius;
        final double distance = minRadius + (maxRadius - minRadius) * Math.pow((double) (System.currentTimeMillis() - startTime) / time, .2);
        if (distance > maxRadius) {
            attack(maxRadius);
//            entity.removeComponent(BoomDiffusionComponent.class);
            FXGL.runOnce(() -> entity.removeComponent(ShockWaveComponent.class), Duration.ZERO);
            return;
        }
        attack(distance);

    }

    private void attack(final double distance) {
        List<Entity> list = FXGL.getGameWorld().getGroup(camp ? PLAYER : ENEMY).getEntitiesCopy();
        // 爆炸的冲击波不会攻击自家阵营的子弹
        if (camp) {
            list = list.stream().filter(entity1 -> {
                Optional<Object> propertyOptional = entity1.getPropertyOptional(PropertyConst.CAMP);
                if (propertyOptional.isPresent()) {
                    return propertyOptional.get() != CampEnum.PLAYER;
                }
                return true;
            }).collect(Collectors.toList());
        } else {
            list = list.stream().filter(entity1 -> entity1.getPropertyOptional(PropertyConst.CAMP).map(o -> o != CampEnum.ENEMY).orElse(true)).collect(Collectors.toList());
        }
        final double centerX = point.getX();
        final double centerY = point.getY();
        for (Entity entity : list) {
            Point2D entityCenter = entity.getCenter();
            final double d = Math.sqrt(Math.pow(centerX - entityCenter.getX(), 2) + Math.pow(centerY - entityCenter.getY(), 2));
            if (d < distance) {
                BaseTankComponent tankComponent = BaseTankComponent.getTankComponent(entity);
                if (tankComponent != null) {
                    // 如果扣过该坦克的血就不扣了
                    if (set.contains(tankComponent)) {
                        continue;
                    }
                    if (!tankComponent.isInvincible()) {
                        tankComponent.underAttack(attack);
                        // 添加到set如果扣过该坦克的血就不扣了
                        set.add(tankComponent);
                    }
                } else if (entity.getType() == GameEnum.HOME) {
                    entity.getComponent(HomeComponent.class).destroy();
                } else {
                    entity.removeFromWorld();
                }
            }
        }
    }
}
